from django.contrib.auth.models import User
from django.core.files import File
from core.models import Level, Member, Address
from shop.models import Category, DessertItem, Sale, SaleEntry
import datetime
import os
import random

# globals
FIRST_NAME_LENGTH = 5
LAST_NAME_LENGTH = 7
MEMBER_NUMBER = 200

def random_pick(population):
    return random.sample(population, 1)[0]

def create_level(**kwargs):
    return Level.objects.create(**kwargs)

random_string = lambda n: ''.join((chr(random.randint(97, 122)) for i in range(n)))
def random_name():
    first_name = random_string(FIRST_NAME_LENGTH)
    last_name = random_string(LAST_NAME_LENGTH)
    username = first_name + '_' + last_name
    name = first_name.capitalize() + ' ' + last_name.capitalize()
    return username, name
    
def create_user(**kwargs):
    return User.objects.create_user(**kwargs)

def create_member(**kwargs):
    return Member.objects.create(**kwargs)

def create_address(**kwargs):
    return Address.objects.create(**kwargs)

def create_category(**kwargs):
    return Category.objects.create(**kwargs)

def create_dessert(**kwargs):
    return DessertItem.objects.create(**kwargs)

def create_sale(**kwargs):
    return Sale.objects.create(**kwargs)

def create_entry(**kwargs):
    return SaleEntry.objects.create(**kwargs)

def daterange(start_date, end_date):
    for n in xrange((end_date - start_date).days):
        yield start_date + datetime.timedelta(n)

def populate():
    # 1. create levels
    name_discount = (
        ('Platinum', 0.8),
        ('Golden', 0.85),
        ('Silver', 0.9),
        ('Bronze', 0.95),
        ('Basic', 1.0),
    )
    n = 1
    LEVEL_POPULATION = []
    for name, discount in name_discount:
        level = create_level(name=name, discount_rate=discount)
        print 'created level: %s' % level
        for i in range(n):
            LEVEL_POPULATION.append(level)
        n *= 2

    # 2. create users
    GENDER_POPULATION = ['M', 'M', 'M', 'F', 'F', 'F', 'F', 'F', 'O']
    PASSWORD = '123123'

    TODAY = datetime.date.today()
    THIS_YEAR = TODAY.year
    TEENAGER = TODAY.replace(year=THIS_YEAR-15)
    YOUTH = TODAY.replace(year=THIS_YEAR-25)
    MIDDLE_AGE = TODAY.replace(year=THIS_YEAR-35)
    SENIOR = TODAY.replace(year=THIS_YEAR-45)
    OLD = TODAY.replace(year=THIS_YEAR-55)
    BIRTHDAY_POPULATION = [YOUTH, YOUTH, YOUTH, YOUTH, YOUTH, YOUTH, YOUTH, YOUTH, YOUTH, YOUTH, TEENAGER, TEENAGER, TEENAGER, TEENAGER, TEENAGER, TEENAGER, MIDDLE_AGE, MIDDLE_AGE, MIDDLE_AGE, MIDDLE_AGE, SENIOR, SENIOR, OLD]

    REGISTER_DATE = datetime.date(2012, 1, 1)
    NEXT_YEAR = TODAY + datetime.timedelta(days=365)
    EXPIRE_DATE_POPULATION = [NEXT_YEAR, NEXT_YEAR, NEXT_YEAR, REGISTER_DATE]

    COUNTRY = 'China'
    STATE_POPULATION = ['Jiangsu', 'Jiangsu', 'Jiangsu', 'Jiangsu', 'Jiangsu', 'Jiangsu', 'Jiangsu', 'Jiangsu', 'Jiangsu', 'Jiangsu', 'Shanghai', 'Shangdong', 'Shanghai', 'Shangdong', 'Shanghai', 'Shangdong', 'Shanghai', 'Shangdong', 'Shanghai', 'Shangdong', 'Shanghai', 'Shangdong', 'Shanghai', 'Shangdong', 'Shanghai', 'Shangdong', 'Zhejiang', 'Anhui', 'Henan', 'Beijing', 'Zhejiang', 'Anhui', 'Henan', 'Beijing', 'Zhejiang', 'Anhui', 'Henan', 'Beijing', 'Zhejiang', 'Anhui', 'Henan', 'Beijing', 'Zhejiang', 'Anhui', 'Henan', 'Beijing', 'Zhejiang', 'Anhui', 'Henan', 'Beijing', 'Tianjin', 'Hebei', 'Shanxi', 'Chongqing', 'Hubei', 'Yunnan', 'Tianjin', 'Hebei', 'Shanxi', 'Chongqing', 'Hubei', 'Yunnan', 'Tianjin', 'Hebei', 'Shanxi', 'Chongqing', 'Hubei', 'Yunnan', 'Tianjin', 'Hebei', 'Shanxi', 'Chongqing', 'Hubei', 'Yunnan', 'Guangxi', 'Guangdong', 'Sichuan', 'Shanxi', 'Gansu' 'Guangxi', 'Guangdong', 'Sichuan', 'Shanxi', 'Gansu' , 'Xizang', 'Menggu', 'Hainan', 'Liaoning', 'Heilongjiang', 'Xinjiang']
    CITY = 'Captital City'
    STREET = 'No.8 Mystique St.'

    member_list = []
    username_list = []
    for i in range(MEMBER_NUMBER):
        # 2.1 male:female:other = 3:5:1
        gender = random_pick(GENDER_POPULATION)
        # 2.2 level 1/2
        level = random_pick(LEVEL_POPULATION)
        # 2.3 name from random chars (Biisfd Kidsfa)
        # 2.4 username is lowered, concatenated fisrt and last name
        username, name = random_name()
        while username in username_list:
            username, name = random_name()
        username_list.append(username)
        email = username + '@example.com'
        # 2.5 password is always 123123
        password = PASSWORD
        # 2.6 birthday: youth > teenagers > middle-aged >> senior
        birthday = random_pick(BIRTHDAY_POPULATION)
        # 2.7 register data is always 2012-01-01
        register_date = REGISTER_DATE
        # 2.8 active/expire rate: 3:1
        expire_date = random_pick(EXPIRE_DATE_POPULATION)
        # 2.9 balance is random (0~200)
        balance = round(random.random()*200, 2)
        # 2.A country is always China
        country = COUNTRY
        # 2.B state is random but with higher probability of eastern provinces
        state = random_pick(STATE_POPULATION)
        # 2.C city and street can be the same
        city, street = CITY, STREET
        user = create_user(username=username, password=password, email=email)
        member = create_member(user=user, level=level, name=name, gender=gender, birthday=birthday, register_date=register_date, expire_date=expire_date, balance=balance)
        print 'created member: %s' % member
        member_list.append(member)
        address = create_address(member=member, country=country, state=state, city=city, street=street)
        print 'created address: %s' % address

    # 3. create categories
    category_names = ('Miscellaneous', 'Cookies', 'Cakes')
    CATEGORY_POPULATION = []
    for category_name in category_names:
        category = create_category(name=category_name)
        print 'created category: %s' % category
        CATEGORY_POPULATION.append(category)

    # 4. create items
    PIC_DIR = 'dessert-pics'
    try:
        pics = os.listdir(PIC_DIR)
    except:
        print 'error opening %s, quitting' % PIC_DIR
        exit()

    ITEM_NAMES = (
        'Malaysia Shangri La Buffet',
        'Traditional Australian Christmas Dessert',
        'Medieval/Renaissance Tray',
        'Beckta Sunshine Cookie',
        'Strawberry and Raspberry Trifle',
        'Baked Chocolate Cupcake Cute Dess',
        'Mascarpone Delicious Master',
        'Indian Dessert Cookie',
        'Candy Chiristmas Cookie',
        'Chocolate Chip Cheesecake',
        'Festive Dessert Pizza',
        'Elegant Strawberry Birthday Cake'
    )
    ITEM_DETAILS = (
        'Made by first-class dessert chef with guaranteed luscious satisfaction!',
        'Received exclamations from connoisseurs. A must try!',
        'Baked by Dessert House\'s ace dessert chef, purely Franch style.',
        'Latest experimental to the next-generation dessert, the future is for you to evaluate.'
        'No marketing hype. Superb quality and superb price, you have both!',
    )
    LEN_DTL = len(ITEM_DETAILS)
    ITEM_POPULATION = []
    for i in range(len(pics)):
        # 4.1 item number equals to unique pic number
        name = ITEM_NAMES[i]
        detail = random_pick(ITEM_DETAILS)
        category = random_pick(CATEGORY_POPULATION)
        pic_path = os.path.join(PIC_DIR, pics[i])
        pic = File(open(pic_path, 'rb'))

        item = create_dessert(pic=pic, name=name, detail=detail, category=category)
        print 'created dessert: %s' % item
        ITEM_POPULATION.append(item)

    # 5. create sales
    # 5.1 sale from 2012-01-01 to today
    # 5.2 sales in later months are greater than those of former
    start_time = datetime.datetime(2012, 1, 1)
    end_time = datetime.datetime.now()
    counter = 0
    sale_per_day = 5
    GROWTH_RATE = 1.3
    PERIOD = 20
    NUMBER_POPULATION = [1, 1, 2, 2, 2, 3, 3, 4, 5, 6]
    for day in daterange(start_time, end_time):
        print 'creating sales for %s' % day
        for i in range(sale_per_day):
            kwargs = {}
            # 5.3 is_paid is always True, discount_rate is always 1.0
            kwargs['is_paid'] = True
            kwargs['paid_time'] = day
            kwargs['discount_rate'] = 1.0
            # 5.4 customer is chosen at random
            kwargs['customer'] = random_pick(member_list)
            # 5.5 purchase/reservation = 3/1
            if counter % 3 == 0:
                kwargs['is_reservation'] = True
                # 5.6 get_day of reservation is always tomorrow
                kwargs['get_day'] = day + datetime.timedelta(days=1)
                # 5.7 is_paid_off is always True with paid_off_time at 12 hours after first round payment
                kwargs['is_paid_off'] = True
                kwargs['paid_off_time'] = day + datetime.timedelta(hours=12)
            sale = create_sale(**kwargs)
            print 'created sale: %s' % sale

            # 5.8 in each sale, there are 1-4 entries
            for j in range(random_pick(NUMBER_POPULATION)):
                # 5.9 item is chosen at random (better with larger probability of some category)
                item = random_pick(ITEM_POPULATION)
                # 5.A quantity is arbitrary (more is less possible)
                quantity = random_pick(NUMBER_POPULATION)
                # 5.B price is around 5-30
                price = round(random.random()*25+5, 2)
                entry = create_entry(sale=sale, item=item, quantity=quantity, price=price)
                print 'created entry: %s' % entry

        counter += 1
        if counter % PERIOD == 0:
            sale_per_day = int(sale_per_day*GROWTH_RATE)
            print ''
            print 'sale per day is now %s' % sale_per_day
            print ''

